package dominio.ubicaciones

import dominio.datos.Caracteristica
import dominio.individuos.CuidadorAjeno
import dominio.individuos.CuidadorEnTrampa
import dominio.individuos.Informante
import dominio.investigacion.Caso
import dominio.investigacion.Mapamundi
import java.io.Serializable
import java.util.ArrayList
import java.util.List
import org.uqbar.commons.model.ObservableUtils
import org.uqbar.commons.model.UserException
import org.uqbar.commons.utils.Observable
import dominio.factory.FactoryGame

@Observable
class Pais implements Serializable {
	
	@Property String nombre
	@Property Caso caso;
	@Property List<Lugar> lugares
	@Property List<Caracteristica> caracteristicas 
	@Property List<Pais> conexiones
	@Property List<Lugar> lugaresPosibles
	
	
	@Property Mapamundi mapamundi
	@Property boolean tieneNombreValido
	
	new() {
		this.lugares = new ArrayList<Lugar>
		this.caracteristicas = new ArrayList<Caracteristica>
		this.conexiones = new ArrayList<Pais>
		this.tieneNombreValido = false
		setearLugaresPosibles
	}
	
	def setearLugaresPosibles() {
		lugaresPosibles = new ArrayList<Lugar> => [
			add(new Biblioteca(this)) 
			add(new Club(this))
			add(new Embajada(this)) 
			add(new Banco(this))
		]
	}
	
	def tieneLugar(String nombreTipoLugar) {
		lugares.exists[l | l.nombreTipoLugar == nombreTipoLugar ]
	}
	
	new(String nombre) {
		new Pais => [ it.nombre = nombre ]
	}
	
	
	def siguientePais(){
		caso.siguiente(this)
	}
	
	def eliminarConexion(Pais pais) {
		pais.conexiones.remove(this)
		conexiones.remove(pais)
		ObservableUtils.firePropertyChanged(this,"conexiones", conexiones)
		ObservableUtils.firePropertyChanged(pais,"conexiones", pais.conexiones)
	}
	
	def agregarConexion(Pais pais) {
		if(!tieneConexionCon(pais)){
			conexiones += pais
			pais.conexiones += this
		} else throw new UserException("Este pais ya tiene una conexion con: " + pais.nombre + "!")
		ObservableUtils.firePropertyChanged(this, "conexiones", conexiones)
		ObservableUtils.firePropertyChanged(pais, "conexiones", pais.conexiones)
	}
	
	def tieneConexionCon(Pais pais) {
		conexiones.contains(pais)
	}
	
	def agregarLugar(Lugar lugar) {
		if(lugares.size < 3) { 
			if(!tieneLugar(lugar.nombreTipoLugar)) {
				lugares += lugar
			} else throw new UserException("Este pais ya tiene el lugar: " + lugar.nombreTipoLugar + "!")
		} else throw new UserException("Solo puede tener 3 (tres) lugares")
		ObservableUtils.firePropertyChanged(this, "lugares", lugares)
	}
	
	def borrarLugar(Lugar lugar) {
		lugares.remove(lugar)
	}
	
	def tieneLosLugaresRequeridos() {
		lugares.size == 3
	}
	
	def validar() {
		if(!esNombreValido)
			throw new UserException("El pais debe tener un nombre valido!")
		
		if(!tieneLosLugaresRequeridos)
			throw new UserException("El pais debe tener exactamente tres lugares de interes!")
	}
	
	def esNombreValido() {
		if(nombre == null) {
			false
		} else {
			nombre = nombre.trim
			nombre.length > 0
		}
	}
	
	def mismoPais(Pais pais) {
		this.nombre == pais.nombre
	}
	
	def setearInformantes() {
		lugares.forEach[l | l.ocupante = new Informante(l)]
	}
	
	def setearCuidadores() {
		lugares.forEach[l | l.ocupante = new CuidadorAjeno]
	}
	
	def setearVillano() {
		
		var randomIndex = (Math.random*(2)).intValue
		lugares.get(randomIndex).ocupante = caso.responsable
		lugares.forEach[l | if(l.ocupante == null) l.ocupante = new CuidadorEnTrampa]
	}
	
	def borrarConexion(Pais pais) {
		this.conexiones.remove(pais)
		pais.conexiones.remove(this)
	}
	
	override toString() {
		this.nombre
	}
	
}